package com.cqu.springmvc.context;

import com.cqu.springmvc.annotation.Autowired;
import com.cqu.springmvc.annotation.Controller;
import com.cqu.springmvc.annotation.Service;
import com.cqu.springmvc.exception.ContextException;
import com.cqu.springmvc.xml.XmlPaser;

import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class WebApplicationContext {

    //classpath:springmvc.xml
    String contextConfigLocation;
    List<String> classNameList = new ArrayList<String>();

    //Spring的IOC容器
    public Map<String,Object> iocMap = new ConcurrentHashMap<String,Object>();


    public WebApplicationContext(String contextConfigLocation) {
        this.contextConfigLocation = contextConfigLocation;
    }

    //初始化Spring容器
    public void refresh() {
        //1.解析springmvc.xml（dom4j）
        String basePackage = XmlPaser.getbasePackage(contextConfigLocation.split(":")[1]);
        String[] basePackages = basePackage.split(",");
        if(basePackages.length > 0) {
            for(String pack :basePackages) {
                //com.cqu.apptest.service
                //com.cqu.apptest.controller
                excuteScanPackage(pack);
            }

            System.out.println("扫描之后的内容：" + classNameList);
            //实例化Spring容器中的bean
            excuteInstance();
            //IOC容器中的对象
            System.out.println("IOC容器中的对象"+iocMap);
            //实现Spring容器中对象的依赖注入
            excuteAutowired();
        }
    }

    //扫描包
    public void excuteScanPackage(String pack) {
        //com/cqu/apptest/service
        URL url = this.getClass().getClassLoader().getResource("/" + pack.replaceAll("\\.", "/"));
        String path = url.getFile();
        File dir = new File(path);
        for(File f : dir.listFiles()) {
            if(f.isDirectory()) {
                //文件目录
                excuteScanPackage(pack + "." + f.getName());
            } else {
                //文件
                String className = pack + "." + f.getName().replace(".class", "");
                classNameList.add(className);
            }
        }

    }

    //实例化Spring容器中的bean
    public void excuteInstance() {
        if(classNameList.size() == 0) {
            //没有扫描到需要示例化的类
            throw new ContextException("没有要实例化的class!");
        }
        try {
            for (String className : classNameList) {
                Class<?> classzz = Class.forName(className);
                if(classzz.isAnnotationPresent(Controller.class)){
                    //controller层的类 com.cqu.apptest.controller.UserController
                    //把 UserController 变成 userController（控制层对象的名字）
                    String beanName = classzz.getSimpleName().substring(0,1).toLowerCase()+classzz.getSimpleName().substring(1);
                    iocMap.put(beanName,classzz.newInstance());
                } else if(classzz.isAnnotationPresent(Service.class)){
                    //service com.cqu.apptest.service.impl.UserServiceImpl
                    Service serviceAnnotation = classzz.getAnnotation(Service.class);
                    String beanName = serviceAnnotation.value();
                    if("".equals(beanName)) {
                        Class<?>[] interfaces = classzz.getInterfaces();
                        for(Class<?> c1 : interfaces) {
                            String beanName1 = c1.getSimpleName().substring(0,1).toLowerCase()+c1.getSimpleName().substring(1);
                            iocMap.put(beanName1, classzz.newInstance());
                        }
                    } else {
                        iocMap.put(beanName, classzz.newInstance());
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }
    }

    //实现Spring容器中对象的依赖注入
    public void excuteAutowired() {
        try {
            if(iocMap.isEmpty()) {
                throw new ContextException("没有找到初始化的bean对象!");
            }
            for(Map.Entry<String,Object> entry : iocMap.entrySet()) {
                String key = entry.getKey();
                Object bean = entry.getValue();
                Field[] declaredFields = bean.getClass().getDeclaredFields();
                for(Field declaredField : declaredFields) {
                    if(declaredField.isAnnotationPresent(Autowired.class)) {
                        Autowired autowiredAnnotation = declaredField.getAnnotation(Autowired.class);
                        String beanName = autowiredAnnotation.value();
                        if("".equals(beanName)) {
                            Class<?> type = declaredField.getType();
                            beanName = type.getSimpleName().substring(0,1).toLowerCase()+type.getSimpleName().substring(1);
                        }
                        declaredField.setAccessible(true);
                        //属性注入  调用反射给属性赋值
                        declaredField.set(bean,iocMap.get(beanName));
                    }
                }
            }
        } catch (IllegalAccessException e){
            e.printStackTrace();
        } finally {
        }
    }


}
